<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>PDF合并工具</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
    <style>
      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
        font-family: 'SF Pro Display', 'PingFang SC', 'Helvetica Neue', Arial,
          sans-serif;
      }

      :root {
        --primary-bg: #e6e7ee;
        --secondary-bg: #ffffff;
        --shadow-light: #ffffff;
        --shadow-dark: #d1d9e6;
        --accent-color: #667eea;
        --accent-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        --success-color: #4ecdc4;
        --danger-color: #ff6b6b;
        --warning-color: #feca57;
        --text-primary: #2d3748;
        --text-secondary: #718096;
        --glass-bg: rgba(255, 255, 255, 0.25);
        --glass-border: rgba(255, 255, 255, 0.18);
      }

      body {
        background: var(--primary-bg);
        color: var(--text-primary);
        min-height: 100vh;
        padding: 20px;
        display: flex;
        flex-direction: column;
        align-items: center;
        transition: all 0.3s ease;
        animation: pageLoad 0.8s ease;
      }

      @keyframes pageLoad {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .container {
        width: 100%;
        max-width: 1200px;
        background: var(--primary-bg);
        border-radius: 30px;
        padding: 40px;
        box-shadow: 20px 20px 60px var(--shadow-dark),
          -20px -20px 60px var(--shadow-light);
        margin-top: 20px;
        transition: all 0.3s ease;
        animation: containerFloat 1s ease 0.2s both;
      }

      @keyframes containerFloat {
        from {
          opacity: 0;
          transform: translateY(30px) scale(0.95);
        }
        to {
          opacity: 1;
          transform: translateY(0) scale(1);
        }
      }

      .container:hover {
        box-shadow: 25px 25px 70px var(--shadow-dark),
          -25px -25px 70px var(--shadow-light);
      }

      header {
        text-align: center;
        margin-bottom: 40px;
        padding: 30px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: headerSlide 0.8s ease 0.4s both;
      }

      @keyframes headerSlide {
        from {
          opacity: 0;
          transform: translateY(-30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      h1 {
        font-size: 3.2rem;
        margin-bottom: 15px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
        font-weight: 700;
        animation: titleGlow 3s ease-in-out infinite alternate;
      }

      @keyframes titleGlow {
        from {
          filter: brightness(1);
        }
        to {
          filter: brightness(1.2);
        }
      }

      .subtitle {
        font-size: 1.3rem;
        color: var(--text-secondary);
        margin-bottom: 30px;
        font-weight: 500;
      }

      .panels {
        display: flex;
        gap: 30px;
        margin-bottom: 40px;
        animation: panelsSlide 0.8s ease 0.6s both;
      }

      @keyframes panelsSlide {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .panel {
        flex: 1;
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
      }

      .panel::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.1),
          transparent
        );
        transition: left 0.8s;
      }

      .panel:hover::before {
        left: 100%;
      }

      .panel:hover {
        transform: translateY(-5px);
        box-shadow: 16px 16px 32px var(--shadow-dark),
          -16px -16px 32px var(--shadow-light);
      }

      .panel-title {
        font-size: 1.6rem;
        margin-bottom: 25px;
        color: var(--accent-color);
        display: flex;
        align-items: center;
        font-weight: 600;
      }

      .panel-title::before {
        content: attr(data-icon);
        margin-right: 12px;
        font-size: 1.8rem;
        animation: iconBounce 2s ease-in-out infinite;
      }

      @keyframes iconBounce {
        0%,
        100% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
      }

      .file-upload {
        border: 3px dashed var(--accent-color);
        border-radius: 25px;
        padding: 50px 40px;
        text-align: center;
        transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
        margin-bottom: 25px;
        cursor: pointer;
        background: var(--primary-bg);
        box-shadow: inset 8px 8px 16px var(--shadow-dark),
          inset -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      .file-upload:hover {
        border-color: var(--success-color);
        transform: translateY(-5px) scale(1.02);
        box-shadow: inset 10px 10px 20px var(--shadow-dark),
          inset -10px -10px 20px var(--shadow-light),
          0 15px 40px rgba(102, 126, 234, 0.25), 0 5px 15px rgba(0, 0, 0, 0.1);
      }

      .file-upload.dragover {
        border-color: var(--success-color);
        background: rgba(78, 205, 196, 0.05);
        transform: scale(1.05);
        box-shadow: inset 12px 12px 24px var(--shadow-dark),
          inset -12px -12px 24px var(--shadow-light),
          0 20px 50px rgba(78, 205, 196, 0.3);
        animation: dragPulse 1s ease-in-out infinite;
      }

      @keyframes dragPulse {
        0%,
        100% {
          border-color: var(--success-color);
        }
        50% {
          border-color: var(--accent-color);
        }
      }

      .file-upload-content {
        position: relative;
        z-index: 1;
      }

      .file-upload-icon {
        font-size: 3.5rem;
        margin-bottom: 20px;
        display: block;
        animation: iconFloat 3s ease-in-out infinite;
        filter: drop-shadow(0 4px 8px rgba(102, 126, 234, 0.2));
      }

      @keyframes iconFloat {
        0%,
        100% {
          transform: translateY(0);
        }
        50% {
          transform: translateY(-10px);
        }
      }

      .file-upload-text {
        font-size: 1.4rem;
        font-weight: 600;
        color: var(--text-primary);
        margin-bottom: 10px;
        background: var(--accent-gradient);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
      }

      .file-upload-subtext {
        font-size: 1.1rem;
        color: var(--text-secondary);
        margin-bottom: 20px;
        font-weight: 500;
      }

      .file-upload-formats {
        font-size: 0.9rem;
        color: var(--accent-color);
        font-weight: 500;
        padding: 8px 16px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 20px;
        display: inline-block;
        margin-bottom: 20px;
      }

      .file-upload input[type='file'] {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        opacity: 0;
        cursor: pointer;
        z-index: 2;
      }

      .pdf-list {
        margin-top: 20px;
        max-height: 400px;
        overflow-y: auto;
      }

      .pdf-item {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 15px;
        margin-bottom: 10px;
        background: var(--primary-bg);
        border-radius: 15px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        transition: all 0.3s ease;
        animation: itemSlideIn 0.5s ease;
      }

      @keyframes itemSlideIn {
        from {
          opacity: 0;
          transform: translateX(-20px);
        }
        to {
          opacity: 1;
          transform: translateX(0);
        }
      }

      .pdf-item:hover {
        transform: translateY(-2px);
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
      }

      .pdf-info {
        display: flex;
        align-items: center;
        flex: 1;
      }

      .pdf-icon {
        font-size: 2rem;
        margin-right: 15px;
        color: var(--danger-color);
      }

      .pdf-details {
        flex: 1;
      }

      .pdf-name {
        font-weight: 600;
        color: var(--text-primary);
        margin-bottom: 5px;
        word-break: break-all;
      }

      .pdf-size {
        font-size: 0.9rem;
        color: var(--text-secondary);
      }

      .pdf-actions {
        display: flex;
        gap: 10px;
        align-items: center;
      }

      .move-btn {
        background: var(--primary-bg);
        border: none;
        padding: 8px 12px;
        border-radius: 10px;
        cursor: pointer;
        font-size: 1.2rem;
        color: var(--accent-color);
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
        transition: all 0.3s ease;
      }

      .move-btn:hover {
        transform: translateY(-2px);
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
      }

      .move-btn:disabled {
        opacity: 0.5;
        cursor: not-allowed;
      }

      .remove-btn {
        background: var(--danger-color);
        color: white;
        border: none;
        padding: 8px 12px;
        border-radius: 10px;
        cursor: pointer;
        font-size: 1rem;
        font-weight: 500;
        transition: all 0.3s ease;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .remove-btn:hover {
        background: #e55555;
        transform: translateY(-2px);
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
      }

      button {
        background: var(--primary-bg);
        color: var(--text-primary);
        border: none;
        padding: 14px 28px;
        border-radius: 15px;
        cursor: pointer;
        font-weight: 600;
        transition: all 0.3s ease;
        font-size: 1rem;
        flex-shrink: 0;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light);
        position: relative;
        overflow: hidden;
      }

      button::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.2),
          transparent
        );
        transition: left 0.5s;
      }

      button:hover::before {
        left: 100%;
      }

      button:hover {
        transform: translateY(-3px);
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
      }

      button:active {
        transform: translateY(0);
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
      }

      button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
        box-shadow: 4px 4px 8px var(--shadow-dark),
          -4px -4px 8px var(--shadow-light);
      }

      .btn-primary {
        background: var(--accent-gradient);
        color: white;
        padding: 16px 32px;
        font-size: 1.1rem;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .btn-primary:hover {
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2),
          0 0 30px rgba(102, 126, 234, 0.3);
      }

      .btn-success {
        background: linear-gradient(
          135deg,
          var(--success-color) 0%,
          #44a08d 100%
        );
        color: white;
        box-shadow: 8px 8px 16px var(--shadow-dark),
          -8px -8px 16px var(--shadow-light),
          inset 0 1px 0 rgba(255, 255, 255, 0.2);
      }

      .progress-container {
        margin: 30px 0;
        animation: progressSlide 0.8s ease 0.8s both;
      }

      @keyframes progressSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .progress-bar {
        height: 16px;
        background: var(--primary-bg);
        border-radius: 20px;
        overflow: hidden;
        margin-bottom: 15px;
        box-shadow: inset 6px 6px 12px var(--shadow-dark),
          inset -6px -6px 12px var(--shadow-light);
        position: relative;
      }

      .progress-fill {
        height: 100%;
        background: var(--accent-gradient);
        width: 0%;
        transition: width 0.3s ease;
        border-radius: 20px;
        box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
        position: relative;
        overflow: hidden;
      }

      .progress-fill::after {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(
          90deg,
          transparent,
          rgba(255, 255, 255, 0.3),
          transparent
        );
        animation: progressShine 2s infinite;
      }

      @keyframes progressShine {
        0% {
          left: -100%;
        }
        100% {
          left: 100%;
        }
      }

      .progress-text {
        text-align: center;
        font-size: 1rem;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .actions {
        display: flex;
        justify-content: center;
        gap: 25px;
        margin-top: 30px;
        animation: actionsSlide 0.8s ease 1s both;
      }

      @keyframes actionsSlide {
        from {
          opacity: 0;
          transform: translateY(20px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .result-panel {
        text-align: center;
        animation: resultPanelSlide 0.8s ease 1.2s both;
      }

      @keyframes resultPanelSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .status-message {
        min-height: 35px;
        margin: 20px 0;
        color: var(--accent-color);
        font-weight: 600;
        font-size: 1.1rem;
        transition: all 0.3s ease;
        text-align: center;
      }

      .status-message.processing {
        animation: statusPulse 1.5s ease-in-out infinite;
      }

      @keyframes statusPulse {
        0%,
        100% {
          opacity: 1;
        }
        50% {
          opacity: 0.6;
        }
      }

      .error-message {
        color: var(--danger-color);
        margin: 20px 0;
        min-height: 35px;
        font-weight: 600;
        font-size: 1.1rem;
        animation: errorShake 0.5s ease;
        text-align: center;
      }

      @keyframes errorShake {
        0%,
        100% {
          transform: translateX(0);
        }
        25% {
          transform: translateX(-5px);
        }
        75% {
          transform: translateX(5px);
        }
      }

      .download-section {
        display: none;
        margin-top: 30px;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 25px;
        box-shadow: 12px 12px 24px var(--shadow-dark),
          -12px -12px 24px var(--shadow-light);
        text-align: center;
        animation: downloadSlide 0.8s ease;
      }

      @keyframes downloadSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .download-title {
        font-size: 1.4rem;
        color: var(--accent-color);
        margin-bottom: 20px;
        font-weight: 600;
      }

      .instructions {
        background: var(--primary-bg);
        border-radius: 25px;
        padding: 30px;
        margin-top: 40px;
        box-shadow: 10px 10px 20px var(--shadow-dark),
          -10px -10px 20px var(--shadow-light);
        animation: instructionsSlide 0.8s ease 1.4s both;
      }

      @keyframes instructionsSlide {
        from {
          opacity: 0;
          transform: translateY(30px);
        }
        to {
          opacity: 1;
          transform: translateY(0);
        }
      }

      .instructions h3 {
        color: var(--accent-color);
        margin-bottom: 20px;
        font-size: 1.4rem;
        font-weight: 600;
      }

      .instructions ol {
        padding-left: 25px;
        margin-bottom: 20px;
      }

      .instructions li {
        margin-bottom: 12px;
        line-height: 1.7;
        color: var(--text-secondary);
        font-weight: 500;
      }

      .instructions p {
        color: var(--text-secondary);
        font-style: italic;
        font-weight: 500;
        padding: 15px;
        background: rgba(102, 126, 234, 0.1);
        border-radius: 15px;
        border-left: 4px solid var(--accent-color);
      }

      footer {
        margin-top: 40px;
        text-align: center;
        color: var(--text-secondary);
        font-size: 0.95rem;
        padding: 25px;
        background: var(--primary-bg);
        border-radius: 20px;
        box-shadow: 6px 6px 12px var(--shadow-dark),
          -6px -6px 12px var(--shadow-light);
        animation: footerFade 0.8s ease 1.6s both;
      }

      @keyframes footerFade {
        from {
          opacity: 0;
        }
        to {
          opacity: 1;
        }
      }

      .empty-state {
        text-align: center;
        padding: 40px 20px;
        color: var(--text-secondary);
        font-size: 1.1rem;
      }

      @media (max-width: 768px) {
        .panels {
          flex-direction: column;
        }

        .container {
          padding: 20px;
        }

        h1 {
          font-size: 2.5rem;
        }

        .pdf-item {
          flex-direction: column;
          gap: 15px;
          align-items: flex-start;
        }

        .pdf-actions {
          width: 100%;
          justify-content: flex-end;
        }
      }

      /* 预览按钮样式 */
      .preview-btn {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
        padding: 8px 12px;
        border-radius: 8px;
        cursor: pointer;
        font-size: 14px;
        transition: all 0.3s ease;
        margin-right: 5px;
      }

      .preview-btn:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
      }

      .btn-preview {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
        padding: 12px 24px;
        border-radius: 12px;
        cursor: pointer;
        font-size: 16px;
        font-weight: 600;
        transition: all 0.3s ease;
        margin-right: 15px;
      }

      .btn-preview:hover {
        transform: translateY(-2px);
        box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4);
      }

      .download-actions {
        display: flex;
        gap: 15px;
        justify-content: center;
        align-items: center;
        flex-wrap: wrap;
      }

      /* 预览弹框样式 */
      .preview-modal {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.8);
        z-index: 1000;
        justify-content: center;
        align-items: center;
      }

      .preview-modal.show {
        display: flex;
      }

      .preview-content {
        background: var(--card-bg, #fff);
        border-radius: 20px;
        width: 90%;
        max-width: 1000px;
        height: 80%;
        max-height: 800px;
        display: flex;
        flex-direction: column;
        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
      }

      .preview-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 20px 25px;
        border-bottom: 1px solid var(--border-color);
        border-radius: 20px 20px 0 0;
      }

      .preview-title {
        margin: 0;
        color: var(--text-primary);
        font-size: 20px;
        font-weight: 600;
      }

      .close-btn {
        background: var(--danger-color);
        color: white;
        border: none;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        cursor: pointer;
        font-size: 20px;
        font-weight: bold;
        transition: all 0.3s ease;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .close-btn:hover {
        background: #c0392b;
        transform: scale(1.1);
      }

      .preview-body {
        flex: 1;
        padding: 0;
        overflow: hidden;
      }

      .preview-frame {
        width: 100%;
        height: 100%;
        border: none;
        border-radius: 0 0 20px 20px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <header>
        <h1>📄 PDF合并工具</h1>
        <p class="subtitle">将多个PDF文件合并为一个完整的PDF文档</p>
      </header>

      <div class="panels">
        <!-- 文件上传面板 -->
        <div class="panel">
          <div class="panel-title" data-icon="📁">文件上传</div>

          <div class="file-upload" id="uploadArea">
            <div class="file-upload-content">
              <span class="file-upload-icon">📄</span>
              <div class="file-upload-text">选择或拖拽PDF文件</div>
              <div class="file-upload-subtext">支持多个文件同时上传</div>
              <div class="file-upload-formats">支持格式: PDF</div>
              <input type="file" id="pdfInput" accept=".pdf" multiple />
            </div>
          </div>

          <div class="pdf-list" id="pdfList">
            <div class="empty-state" id="emptyState">
              📋 暂无PDF文件，请上传要合并的PDF文件
            </div>
          </div>
        </div>

        <!-- 设置面板 -->
        <div class="panel">
          <div class="panel-title" data-icon="⚙️">合并设置</div>

          <div class="settings-info">
            <div class="info-item">
              <span class="info-label">📊 文件数量:</span>
              <span class="info-value" id="fileCount">0</span>
            </div>
            <div class="info-item" style="margin-top: 10px">
              <span class="info-label">📏 总大小:</span>
              <span class="info-value" id="totalSize">0 KB</span>
            </div>
          </div>

          <div class="merge-options" style="margin-top: 30px">
            <h4 style="color: var(--accent-color); margin-bottom: 15px">
              📋 合并选项
            </h4>
            <div class="option-item">
              <label>
                <input type="checkbox" id="addBookmarks" checked />
                <span>添加书签 (以文件名为书签)</span>
              </label>
            </div>
            <div class="option-item" style="margin-top: 10px">
              <label>
                <input type="checkbox" id="addPageNumbers" />
                <span>添加页码</span>
              </label>
            </div>
          </div>

          <div class="actions">
            <button class="btn-primary" id="mergeBtn" disabled>
              🔗 开始合并
            </button>
            <button id="clearBtn">🗑️ 清空列表</button>
          </div>
        </div>
      </div>

      <!-- 进度显示 -->
      <div class="progress-container">
        <div class="progress-bar">
          <div class="progress-fill" id="progressFill"></div>
        </div>
        <div class="progress-text" id="progressText">🚀 准备就绪</div>
      </div>

      <!-- 状态信息 -->
      <div class="status-message" id="statusMessage"></div>
      <div class="error-message" id="errorMessage"></div>

      <!-- 下载区域 -->
      <div class="download-section" id="downloadSection">
        <div class="download-title">✅ 合并完成！</div>
        <div class="download-actions">
          <button class="btn-preview" id="previewMergedBtn">
            👁️ 预览合并结果
          </button>
          <button class="btn-success" id="downloadBtn">
            📥 下载合并后的PDF
          </button>
        </div>
      </div>

      <!-- 使用说明 -->
      <div class="instructions">
        <h3>📖 使用说明</h3>
        <ol>
          <li>选择或拖拽多个PDF文件到上传区域</li>
          <li>通过上下箭头调整PDF文件的合并顺序</li>
          <li>选择合并选项（书签、页码等）</li>
          <li>点击"开始合并"按钮进行处理</li>
          <li>合并完成后点击下载按钮保存文件</li>
        </ol>
        <p>
          💡
          提示：文件完全在浏览器中处理，不会上传到服务器，保护您的隐私安全。支持大文件合并，处理速度快。
        </p>
      </div>

      <footer>
        <p>🔧 基于 PDF-lib 技术 | 🌐 完全在浏览器中运行，保护您的隐私</p>
      </footer>
    </div>

    <!-- PDF预览弹框 -->
    <div id="previewModal" class="preview-modal">
      <div class="preview-content">
        <div class="preview-header">
          <h3 class="preview-title" id="previewTitle">PDF预览</h3>
          <button class="close-btn" id="closePreview">×</button>
        </div>
        <div class="preview-body">
          <iframe id="previewFrame" class="preview-frame"></iframe>
        </div>
      </div>
    </div>

    <script>
      let pdfFiles = []
      let mergedPdfBlob = null

      // DOM 元素
      const uploadArea = document.getElementById('uploadArea')
      const pdfInput = document.getElementById('pdfInput')
      const pdfList = document.getElementById('pdfList')
      const emptyState = document.getElementById('emptyState')
      const fileCount = document.getElementById('fileCount')
      const totalSize = document.getElementById('totalSize')
      const addBookmarks = document.getElementById('addBookmarks')
      const addPageNumbers = document.getElementById('addPageNumbers')
      const mergeBtn = document.getElementById('mergeBtn')
      const clearBtn = document.getElementById('clearBtn')
      const progressFill = document.getElementById('progressFill')
      const progressText = document.getElementById('progressText')
      const statusMessage = document.getElementById('statusMessage')
      const errorMessage = document.getElementById('errorMessage')
      const downloadSection = document.getElementById('downloadSection')
      const downloadBtn = document.getElementById('downloadBtn')
      const previewMergedBtn = document.getElementById('previewMergedBtn')
      const previewModal = document.getElementById('previewModal')
      const previewTitle = document.getElementById('previewTitle')
      const previewFrame = document.getElementById('previewFrame')
      const closePreview = document.getElementById('closePreview')

      // 初始化事件
      function initEvents() {
        // 文件上传事件
        pdfInput.addEventListener('change', handleFileUpload)
        uploadArea.addEventListener('click', (e) => {
          // 防止重复触发文件选择
          if (e.target === pdfInput) {
            return
          }

          if (
            e.target === uploadArea ||
            e.target.closest('.file-upload-content')
          ) {
            e.preventDefault()
            e.stopPropagation()
            pdfInput.click()
          }
        })

        // 拖拽事件
        uploadArea.addEventListener('dragover', (e) => {
          e.preventDefault()
          uploadArea.classList.add('dragover')
        })

        uploadArea.addEventListener('dragleave', (e) => {
          e.preventDefault()
          uploadArea.classList.remove('dragover')
        })

        uploadArea.addEventListener('drop', (e) => {
          e.preventDefault()
          uploadArea.classList.remove('dragover')

          if (e.dataTransfer.files.length) {
            handleFileUpload({ target: { files: e.dataTransfer.files } })
          }
        })

        // 按钮事件
        mergeBtn.addEventListener('click', mergePDFs)
        clearBtn.addEventListener('click', clearAllFiles)
        downloadBtn.addEventListener('click', downloadMergedPDF)
        previewMergedBtn.addEventListener('click', previewMergedPDF)

        // 预览弹框事件
        closePreview.addEventListener('click', closePreviewModal)
        previewModal.addEventListener('click', (e) => {
          if (e.target === previewModal) {
            closePreviewModal()
          }
        })

        // ESC键关闭预览
        document.addEventListener('keydown', (e) => {
          if (e.key === 'Escape' && previewModal.classList.contains('show')) {
            closePreviewModal()
          }
        })
      }

      // 处理文件上传
      function handleFileUpload(event) {
        const files = Array.from(event.target.files)

        files.forEach((file) => {
          if (file.type === 'application/pdf') {
            // 检查是否已存在同名文件
            const existingIndex = pdfFiles.findIndex(
              (f) => f.name === file.name
            )
            if (existingIndex === -1) {
              pdfFiles.push(file)
            } else {
              // 替换同名文件
              pdfFiles[existingIndex] = file
            }
          } else {
            showError(`❌ "${file.name}" 不是有效的PDF文件`)
          }
        })

        updatePDFList()
        updateStats()
        pdfInput.value = '' // 清空input以允许重复选择同一文件
      }

      // 更新PDF列表显示
      function updatePDFList() {
        if (pdfFiles.length === 0) {
          pdfList.innerHTML =
            '<div class="empty-state" id="emptyState">📋 暂无PDF文件，请上传要合并的PDF文件</div>'
          mergeBtn.disabled = true
          return
        }

        emptyState.style.display = 'none'
        mergeBtn.disabled = false

        pdfList.innerHTML = pdfFiles
          .map(
            (file, index) => `
          <div class="pdf-item" data-index="${index}">
            <div class="pdf-info">
              <div class="pdf-icon">📄</div>
              <div class="pdf-details">
                <div class="pdf-name">${file.name}</div>
                <div class="pdf-size">${formatFileSize(file.size)}</div>
              </div>
            </div>
            <div class="pdf-actions">
              <button class="preview-btn" onclick="previewPDF(${index})" title="预览PDF">👁️</button>
              <button class="move-btn" onclick="movePDF(${index}, -1)" ${
              index === 0 ? 'disabled' : ''
            }>⬆️</button>
              <button class="move-btn" onclick="movePDF(${index}, 1)" ${
              index === pdfFiles.length - 1 ? 'disabled' : ''
            }>⬇️</button>
              <button class="remove-btn" onclick="removePDF(${index})">🗑️</button>
            </div>
          </div>
        `
          )
          .join('')
      }

      // 移动PDF文件位置
      function movePDF(index, direction) {
        const newIndex = index + direction
        if (newIndex >= 0 && newIndex < pdfFiles.length) {
          ;[pdfFiles[index], pdfFiles[newIndex]] = [
            pdfFiles[newIndex],
            pdfFiles[index],
          ]
          updatePDFList()
        }
      }

      // 删除PDF文件
      function removePDF(index) {
        pdfFiles.splice(index, 1)
        updatePDFList()
        updateStats()
      }

      // 清空所有文件
      function clearAllFiles() {
        if (pdfFiles.length > 0 && confirm('🤔 确定要清空所有PDF文件吗？')) {
          pdfFiles = []
          updatePDFList()
          updateStats()
          hideDownloadSection()
          clearMessages()
        }
      }

      // 更新统计信息
      function updateStats() {
        fileCount.textContent = pdfFiles.length
        const total = pdfFiles.reduce((sum, file) => sum + file.size, 0)
        totalSize.textContent = formatFileSize(total)
      }

      // 合并PDF文件
      async function mergePDFs() {
        if (pdfFiles.length < 2) {
          showError('❌ 至少需要2个PDF文件才能合并')
          return
        }

        try {
          mergeBtn.disabled = true
          statusMessage.textContent = '🔄 正在合并PDF文件...'
          statusMessage.classList.add('processing')
          progressText.textContent = '正在处理...'
          clearMessages()

          // 创建新的PDF文档
          const mergedPdf = await PDFLib.PDFDocument.create()

          // 逐个处理PDF文件
          for (let i = 0; i < pdfFiles.length; i++) {
            const file = pdfFiles[i]
            const progress = ((i + 1) / pdfFiles.length) * 100

            progressFill.style.width = `${progress}%`
            progressText.textContent = `正在处理: ${file.name} (${i + 1}/${
              pdfFiles.length
            })`
            statusMessage.textContent = `🔄 正在合并第 ${i + 1} 个文件: ${
              file.name
            }`

            // 读取PDF文件
            const arrayBuffer = await file.arrayBuffer()
            const pdf = await PDFLib.PDFDocument.load(arrayBuffer)

            // 获取所有页面
            const pageIndices = pdf.getPageIndices()
            const pages = await mergedPdf.copyPages(pdf, pageIndices)

            // 添加书签（如果启用）
            if (addBookmarks.checked) {
              const bookmarkTitle = file.name.replace('.pdf', '')
              // 注意：PDF-lib 的书签功能可能有限，这里只是示例
              // 实际实现可能需要更复杂的逻辑
            }

            // 添加页面到合并的PDF
            pages.forEach((page) => mergedPdf.addPage(page))

            // 小延迟以显示进度
            await new Promise((resolve) => setTimeout(resolve, 100))
          }

          // 如果启用页码，添加页码（简化实现）
          if (addPageNumbers.checked) {
            const pages = mergedPdf.getPages()
            pages.forEach((page, index) => {
              const { width, height } = page.getSize()
              page.drawText(`${index + 1}`, {
                x: width - 50,
                y: 20,
                size: 10,
                color: PDFLib.rgb(0.5, 0.5, 0.5),
              })
            })
          }

          // 生成合并后的PDF
          statusMessage.textContent = '📦 正在生成最终PDF文件...'
          const pdfBytes = await mergedPdf.save()
          mergedPdfBlob = new Blob([pdfBytes], { type: 'application/pdf' })

          // 完成
          progressFill.style.width = '100%'
          progressText.textContent = '✅ 合并完成！'
          statusMessage.textContent = `✅ 成功合并 ${pdfFiles.length} 个PDF文件！`
          statusMessage.classList.remove('processing')

          showDownloadSection()
        } catch (error) {
          console.error('合并失败:', error)
          showError(`❌ 合并失败: ${error.message}`)
          statusMessage.classList.remove('processing')
          mergeBtn.disabled = false
        }
      }

      // 下载合并后的PDF
      function downloadMergedPDF() {
        if (!mergedPdfBlob) {
          showError('❌ 没有可下载的文件')
          return
        }

        const timestamp = new Date()
          .toISOString()
          .slice(0, 19)
          .replace(/:/g, '-')
        const filename = `合并PDF_${timestamp}.pdf`

        const a = document.createElement('a')
        a.href = URL.createObjectURL(mergedPdfBlob)
        a.download = filename
        a.click()

        statusMessage.textContent = '📥 PDF文件下载中...'
      }

      // 显示下载区域
      function showDownloadSection() {
        downloadSection.style.display = 'block'
      }

      // 隐藏下载区域
      function hideDownloadSection() {
        downloadSection.style.display = 'none'
        mergedPdfBlob = null
      }

      // 显示错误信息
      function showError(message) {
        errorMessage.textContent = message
        errorMessage.classList.add('error-shake')
        setTimeout(() => {
          errorMessage.classList.remove('error-shake')
        }, 500)
      }

      // 清空消息
      function clearMessages() {
        errorMessage.textContent = ''
      }

      // 预览单个PDF文件
      function previewPDF(index) {
        const file = pdfFiles[index]
        if (!file) return

        const fileUrl = URL.createObjectURL(file)
        previewTitle.textContent = `PDF预览 - ${file.name}`
        previewFrame.src = fileUrl
        previewModal.classList.add('show')

        // 清理URL对象
        previewFrame.onload = () => {
          setTimeout(() => {
            URL.revokeObjectURL(fileUrl)
          }, 1000)
        }
      }

      // 预览合并后的PDF
      function previewMergedPDF() {
        if (!mergedPdfBlob) {
          showError('❌ 没有可预览的合并文件')
          return
        }

        const fileUrl = URL.createObjectURL(mergedPdfBlob)
        previewTitle.textContent = 'PDF预览 - 合并结果'
        previewFrame.src = fileUrl
        previewModal.classList.add('show')

        // 清理URL对象
        previewFrame.onload = () => {
          setTimeout(() => {
            URL.revokeObjectURL(fileUrl)
          }, 1000)
        }
      }

      // 关闭预览弹框
      function closePreviewModal() {
        previewModal.classList.remove('show')
        previewFrame.src = ''
      }

      // 格式化文件大小
      function formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes'
        const k = 1024
        const sizes = ['Bytes', 'KB', 'MB', 'GB']
        const i = Math.floor(Math.log(bytes) / Math.log(k))
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
      }

      // 初始化
      initEvents()
    </script>
  </body>
</html>
